/**
 * Frida脚本：完整跟踪ep和AES密钥的生成流程
 * 
 * 这个脚本会：
 * 1. 捕获所有密钥生成操作
 * 2. 跟踪ep从生成到加密的完整流程
 * 3. 记录AES加密时使用的密钥
 * 4. 验证ep原始值 = AES密钥的假设
 */

console.log("\n" + "=".repeat(80));
console.log("数美SDK - 完整密钥流程跟踪");
console.log("=".repeat(80));

// ============================================================================
// 工具函数
// ============================================================================

function bytesToHex(bytes) {
    if (!bytes) return "null";
    let hex = "";
    for (let i = 0; i < bytes.length; i++) {
        hex += ("0" + bytes[i].toString(16)).slice(-2);
    }
    return hex;
}

function printBuffer(label, buf, maxLen = 128) {
    if (!buf) {
        console.log(label + ": null");
        return;
    }
    const len = buf.length;
    const displayLen = Math.min(len, maxLen);
    const bytes = [];
    for (let i = 0; i < displayLen; i++) {
        bytes.push(buf[i]);
    }
    console.log(label + ": (" + len + " bytes)");
    console.log("  " + bytesToHex(bytes));
    if (len > maxLen) {
        console.log("  (showing first " + maxLen + " of " + len + " bytes)");
    }
}

function saveToFile(filename, content) {
    const file = new File("/data/local/tmp/" + filename, "w");
    file.write(content);
    file.close();
    console.log("✓ 保存到: /data/local/tmp/" + filename);
}

// ============================================================================
// 全局变量：记录捕获的数据
// ============================================================================

let capturedKeys = {
    randomBytes32: [],      // 所有32字节的随机数
    rsaPlaintext: [],       // RSA加密前的明文
    rsaCiphertext: [],      // RSA加密后的密文
    aesKeys: [],            // AES加密使用的密钥
    aesIVs: [],             // AES加密使用的IV
    epOriginal: null,       // ep的原始值
    epEncrypted: null       // ep加密后的值
};

// ============================================================================
// Hook设置
// ============================================================================

const soName = "libsmsdk.so";
let soModule = null;

function waitForModule() {
    soModule = Process.findModuleByName(soName);
    if (soModule) {
        console.log("✓ 找到SO库: " + soName);
        console.log("  Base: " + soModule.base);
        setupHooks();
    } else {
        setTimeout(waitForModule, 100);
    }
}

function setupHooks() {
    console.log("\n" + "=".repeat(80));
    console.log("设置Hook点");
    console.log("=".repeat(80));
    
    // ------------------------------------------------------------------------
    // 1. Hook随机数生成
    // ------------------------------------------------------------------------
    console.log("\n[1] Hook随机数生成函数");
    
    const randBytes = Module.findExportByName("libcrypto.so", "RAND_bytes");
    if (randBytes) {
        console.log("  ✓ RAND_bytes @ " + randBytes);
        Interceptor.attach(randBytes, {
            onEnter: function(args) {
                this.buf = args[0];
                this.len = args[1].toInt32();
            },
            onLeave: function(retval) {
                if (this.len === 32) {
                    const bytes = this.buf.readByteArray(this.len);
                    const hex = bytesToHex(Array.from(new Uint8Array(bytes)));
                    
                    capturedKeys.randomBytes32.push(hex);
                    
                    console.log("\n🎲 RAND_bytes 生成32字节:");
                    printBuffer("    ", bytes);
                    console.log("    ⚠️  可能是AES-256密钥或ep原始值");
                }
            }
        });
    }
    
    // ------------------------------------------------------------------------
    // 2. Hook RSA加密
    // ------------------------------------------------------------------------
    console.log("\n[2] Hook RSA加密函数");
    
    const rsaEncrypt = Module.findExportByName("libcrypto.so", "RSA_public_encrypt");
    if (rsaEncrypt) {
        console.log("  ✓ RSA_public_encrypt @ " + rsaEncrypt);
        Interceptor.attach(rsaEncrypt, {
            onEnter: function(args) {
                this.flen = args[0].toInt32();
                this.from = args[1];
                this.to = args[2];
                
                if (this.flen > 0 && this.flen <= 256) {
                    const plaintext = this.from.readByteArray(this.flen);
                    const hex = bytesToHex(Array.from(new Uint8Array(plaintext)));
                    
                    capturedKeys.rsaPlaintext.push(hex);
                    
                    console.log("\n🔐 RSA_public_encrypt 加密:");
                    printBuffer("    明文", plaintext);
                    
                    if (this.flen === 32) {
                        console.log("    ⚠️⚠️⚠️ 32字节！这很可能是ep原始值！⚠️⚠️⚠️");
                        capturedKeys.epOriginal = hex;
                    }
                }
            },
            onLeave: function(retval) {
                const encLen = retval.toInt32();
                if (encLen > 0 && this.to) {
                    const ciphertext = this.to.readByteArray(encLen);
                    const hex = bytesToHex(Array.from(new Uint8Array(ciphertext)));
                    
                    capturedKeys.rsaCiphertext.push(hex);
                    
                    printBuffer("    密文", ciphertext);
                    
                    if (this.flen === 32) {
                        console.log("    ⚠️⚠️⚠️ 这可能是加密后的ep！⚠️⚠️⚠️");
                        capturedKeys.epEncrypted = hex;
                    }
                }
            }
        });
    }
    
    // ------------------------------------------------------------------------
    // 3. Hook AES密钥设置
    // ------------------------------------------------------------------------
    console.log("\n[3] Hook AES密钥设置函数");
    
    const aesSetKey = Module.findExportByName("libcrypto.so", "AES_set_encrypt_key");
    if (aesSetKey) {
        console.log("  ✓ AES_set_encrypt_key @ " + aesSetKey);
        Interceptor.attach(aesSetKey, {
            onEnter: function(args) {
                const keyPtr = args[0];
                const bits = args[1].toInt32();
                const keyLen = bits / 8;
                
                if (keyLen > 0 && keyLen <= 64) {
                    const key = keyPtr.readByteArray(keyLen);
                    const hex = bytesToHex(Array.from(new Uint8Array(key)));
                    
                    capturedKeys.aesKeys.push(hex);
                    
                    console.log("\n🔑 AES_set_encrypt_key:");
                    console.log("    密钥长度: " + bits + " bits");
                    printBuffer("    密钥", key);
                }
            }
        });
    }
    
    // ------------------------------------------------------------------------
    // 4. Hook SO内部AES加密函数
    // ------------------------------------------------------------------------
    console.log("\n[4] Hook SO内部AES加密函数");
    
    const aesEncAddr = soModule.base.add(0x4AAE4);
    console.log("  ✓ sub_4AAE4 @ " + aesEncAddr);
    
    Interceptor.attach(aesEncAddr, {
        onEnter: function(args) {
            const dataPtr = args[0];
            const dataLen = args[1].toInt32();
            const outputPtr = args[2];
            const keyPtr = args[3];
            const keyLen = args[4].toInt32();
            const ivPtr = args[5];
            
            console.log("\n📦 sub_4AAE4 (AES加密):");
            console.log("    数据长度: " + dataLen);
            console.log("    密钥长度: " + keyLen);
            
            // 捕获密钥
            if (keyLen > 0 && keyLen <= 64) {
                const key = keyPtr.readByteArray(keyLen);
                const hex = bytesToHex(Array.from(new Uint8Array(key)));
                
                if (!capturedKeys.aesKeys.includes(hex)) {
                    capturedKeys.aesKeys.push(hex);
                }
                
                printBuffer("    AES密钥", key);
            }
            
            // 捕获IV
            if (ivPtr && !ivPtr.isNull()) {
                const iv = ivPtr.readByteArray(16);
                const hex = bytesToHex(Array.from(new Uint8Array(iv)));
                
                if (!capturedKeys.aesIVs.includes(hex)) {
                    capturedKeys.aesIVs.push(hex);
                }
                
                printBuffer("    IV", iv);
            }
            
            // 显示部分输入数据
            if (dataLen > 0 && dataLen <= 4096) {
                const data = dataPtr.readByteArray(Math.min(dataLen, 64));
                printBuffer("    输入", data, 64);
            }
        }
    });
    
    // ------------------------------------------------------------------------
    // 5. Hook Java层的getDeviceId
    // ------------------------------------------------------------------------
    console.log("\n[5] Hook Java层getDeviceId");
    
    Java.perform(function() {
        const SmAntiFraud = Java.use("com.ishumei.smantifraud.SmAntiFraud");
        
        SmAntiFraud.getDeviceId.implementation = function() {
            console.log("\n📱 SmAntiFraud.getDeviceId() 调用");
            
            const result = this.getDeviceId();
            
            console.log("    返回: " + result);
            
            // 分析结果
            analyzeResult(result);
            
            return result;
        };
    });
    
    console.log("\n" + "=".repeat(80));
    console.log("✓ 所有Hook设置完成，等待调用...");
    console.log("=".repeat(80) + "\n");
}

// ============================================================================
// 结果分析
// ============================================================================

function analyzeResult(deviceId) {
    console.log("\n" + "=".repeat(80));
    console.log("分析结果");
    console.log("=".repeat(80));
    
    // 从deviceId中提取ep
    try {
        const json = JSON.parse(deviceId);
        if (json.detail && json.detail.ep) {
            const epBase64 = json.detail.ep;
            console.log("\n✓ 提取到ep (Base64): " + epBase64.substring(0, 50) + "...");
            
            // 转换为hex
            const epBytes = Array.from(Java.use("android.util.Base64").decode(
                Java.use("java.lang.String").$new(epBase64),
                0
            ));
            const epHex = bytesToHex(epBytes);
            
            console.log("✓ ep (Hex): " + epHex.substring(0, 100) + "...");
            
            // 比对
            console.log("\n" + "-".repeat(80));
            console.log("比对分析：");
            console.log("-".repeat(80));
            
            // 检查ep是否与RSA密文匹配
            if (capturedKeys.rsaCiphertext.length > 0) {
                const matched = capturedKeys.rsaCiphertext.some(ct => ct === epHex);
                if (matched) {
                    console.log("✓ ep匹配RSA密文！");
                } else {
                    console.log("✗ ep不匹配任何RSA密文");
                }
            }
            
            // 显示可能的ep原始值
            if (capturedKeys.epOriginal) {
                console.log("\n可能的ep原始值:");
                console.log("  " + capturedKeys.epOriginal);
            }
            
            // 显示所有AES密钥
            if (capturedKeys.aesKeys.length > 0) {
                console.log("\n捕获的AES密钥 (" + capturedKeys.aesKeys.length + "个):");
                capturedKeys.aesKeys.forEach((key, i) => {
                    console.log("  [" + i + "] " + key);
                    
                    // 检查是否与ep原始值匹配
                    if (capturedKeys.epOriginal && key.startsWith(capturedKeys.epOriginal.substring(0, 64))) {
                        console.log("      ⚠️⚠️⚠️ 与ep原始值匹配！这就是答案！⚠️⚠️⚠️");
                    }
                });
            }
            
            // 保存结果
            const summary = {
                epOriginal: capturedKeys.epOriginal,
                epEncrypted: epHex,
                aesKeys: capturedKeys.aesKeys,
                aesIVs: capturedKeys.aesIVs,
                randomBytes32: capturedKeys.randomBytes32,
                timestamp: new Date().toISOString()
            };
            
            console.log("\n保存结果...");
            saveToFile("key_analysis.json", JSON.stringify(summary, null, 2));
            
        }
    } catch (e) {
        console.log("✗ 解析deviceId失败: " + e);
    }
}

// ============================================================================
// 启动
// ============================================================================

setTimeout(waitForModule, 100);



